using Digitalmes.Domain;
using Digitalmes.Infrastructure.Scada.Handlers;
using ThingsEdge.Exchange.Contracts;
using ThingsEdge.Exchange.Forwarders;

namespace Digitalmes.Infrastructure.Scada.Forwarders;

/// <summary>
/// 请求消息（触发）处理。
/// </summary>
internal sealed class NativeTriggerForwarder(IServiceProvider serviceProvider, ILogger<NativeTriggerForwarder> logger) : ITriggerForwarder
{
    /// <summary>
    /// 单一信号点。进/出站、扫码登只允许存在唯一的信号点。
    /// </summary>
    private static readonly Dictionary<string, Type> _singleHandlerMap = new()
    {
        { TagDefinition.PLC_Inbound_Sign, typeof(InboundHandler) },
        { TagDefinition.PLC_Outbound_Sign, typeof(OutboundHandler) },
        { TagDefinition.PLC_ScanKey_Sign, typeof(ScanKeyHandler) },
        { TagDefinition.PLC_ScanBatch_Sign, typeof(ScanBatchHandler) },
        { TagDefinition.PLC_ReworkFeeding_Sign, typeof(ReworkFeedingHandler) },
    };

    public async Task<ResponseMessage> HandleAsync(RequestMessage message, CancellationToken cancellationToken = default)
    {
        ResponseMessage response = new()
        {
            Request = message,
        };

        ScadaResult result;
        var self = message.Self();

        // 工步操作可能会同时进行，或是可能有多种，校验前缀
        if (self.TagName.StartsWith(TagDefinition.PLC_StepTask_Sign))
        {
            var handler = serviceProvider.GetRequiredService<StepTaskHandler>();
            result = await handler.HandleAsync(message, cancellationToken);
        }
        else if (self.TagName.StartsWith(TagDefinition.PLC_Inspect_Sign))
        {
            var handler = serviceProvider.GetRequiredService<EquipmentInspectHandler>();
            result = await handler.HandleAsync(message, cancellationToken);
        }
        else if (_singleHandlerMap.TryGetValue(self.TagName, out var type))
        {
            var handler = (IScadaAskHandler)serviceProvider.GetRequiredService(type);
            result = await handler.HandleAsync(message, cancellationToken);
        }
        else
        {
            logger.LogWarning("请求的标记名称 {TagName} 必须属于 {@Tags} 其中的一种。", self.TagName, _singleHandlerMap.Keys);
            result = new() { State = (int)ErrorCode.E0003 };
        }

        response.State = result.State;
        response.CallbackItems = result.CallbackItems;
        return response;
    }
}
